

#include "MyMessages.h"
#include "MyShots.h"
#include "MyDefinitions.h"
#include "MyUniversal.h"
#include "MyEngine.h"
#include "MyGame.h"
#include "MyPlayer.h"
#include "MyPlayerActionManager.h"
#include "MyInfobar.h"
#include "MyEnemies.h"
#include "MyScenery.h"
#include "MySplashScreen.h"

MyGame::MyGame(MyEngine* _this)
{
	parent = _this;
	actGameState = GS_INIT;
}
MyGame::~MyGame(){ clean_game();
#ifdef _DEBUG
	printf("destroyed game\n");
#endif
}
void MyGame::init_game()
{
 actGameState = GS_INIT;
 init_colors();
 
 //init the infobar object
 actInfobar = new MyInfobar(this);
 actInfobar->load_imgs();
 
 actScenery = new MyScenery(this);
 actScenery->draw_scenery(0);

 //init the player object
 actPlayer = new MyPlayer(this);
 actPlayer -> reset();

 //init the action manager object
 actPlayerActionManager = new MyPlayerActionManager(this);
 actPlayerActionManager->init();
 
 //init the enemies object
 actEnemies = new MyEnemies(this);
 actEnemies->init_enemies(); 

 //init the messages object
 actMessages = new MyMessages(this);	
 actMessages->init_messages();

 //actMessages->add_message(4000,12,12,12,12,"xx", 0,0);

 //init the projectils object
 actProjectils = new MyShots(this);
 actProjectils->init_projectils();

 //all init was ok
 actGameState = GS_PLAY;

 //draw the screen
 draw_all(0);
}
void MyGame::demand_quit()
{
	parent->goto_gs(ES_QUIT);
}
void MyGame::init_colors()
{
	//init of game colors
	color_bar1  =  make_color(36,36,36);		//dark grey
	color_bar2  =  make_color(140,140,140);		//light grey
	color_life1 = make_color(0xff,0x1a,0x1a);	//light red
	color_life2 = make_color(115,11,13);		//dark red
	color_mana1 = make_color(0x1c,0x1c,0xdc);	//light blue
	color_mana2 = make_color(0,0,80);			//navy/dark blue
	color_exp1  =  make_color(0xFF,0xC5,0x00);	//gold		
	color_black = make_color(1,1,1);			//black 
	color_white = make_color(255,255,255);		//white
	color_wood1 = make_color(74,67,44);			//light brown
	color_wood2 = make_color(40,37,33);			//dark brown
	color_red = make_color(255,0,0);
}

//DEINIT -- cleans all the subobjects & SDL_Surfaces
void MyGame::clean_game(){	
	if (actGameState != GS_INIT)
	{		
		delete(actScenery);
		delete(actPlayer);
		delete(actInfobar);
		delete(actEnemies);
		delete(actProjectils);
	}
	if (actGameState == GS_NEXTLVL)
	{
		delete(actSplashScreen);
	}
}
//DRAW -- functions to display the i)scenery ii)player, enemies, projectils

void MyGame::draw_all(int _t)
{
	switch (actGameState)
	{
		case GS_LVLFINISHED:
			{
				actScenery->draw_scenery(_t);		
				actSplashScreen = new MySplashScreen(this);
				actGameState = GS_NEXTLVL;
				break;
			}
		case GS_NEXTLVL:
			{
				actScenery->draw_scenery(_t);						
				actSplashScreen->displaySplashScreen(_t);
				break;
			}
		case GS_PLAY:
			{
				actScenery->draw_scenery(_t);		
				actProjectils->draw_projectils(_t);
				actEnemies->generate_enemy_group(_t);
				actEnemies->draw_enemies(_t);
				actPlayer->move_player(_t);
				actInfobar->draw_infobar();
				actMessages->draw_messages(_t);	
				break;
			}
	}

}
void MyGame::level_up_trigger()
{
	//display level up message
	actMessages->add_border_text_message(5000,"Congratulations! Level UP!",color_exp1);	
	if ((actPlayer->get_level() > 3) && (actEnemies->enemySpawnLevel < 2))
	{
		actEnemies->enemySpawnLevel = 2;
		actMessages->add_text_message(6000, SCREEN_W-200, 0, SCREEN_W-200, SCREEN_H-INFOBAR_H-18,"Beware! New type of heretic's commin'!",color_black,color_black);
	}
	if ((actPlayer->get_level() > 6) && (actEnemies->enemySpawnLevel < 3))
	{
		actEnemies->enemySpawnLevel = 3;
		actMessages->add_text_message(6000, SCREEN_W-200, 0, SCREEN_W-200, SCREEN_H-INFOBAR_H-18,"Beware! New type of heretic's commin'!",color_black,color_black);
	}
}
//EVENTS
void MyGame::process_event(SDL_Event& handle_event,int _t)
{
	switch(actGameState)
	{
		case GS_INIT: 
		{
			//do all the initializing
			init_game();	
			break;    
		}
		case GS_PLAY: 
		{ 
			switch (handle_event.type)
			{
				//keypressed
				case SDL_KEYDOWN:
				{	
					//check if the pressed key is usefull for player
					switch (handle_event.key.keysym.sym)
					{
						#ifdef _DEBUG
						//function key FOR _DEBUG ONLY
						case SDLK_F1: { this->actGameState = GS_LVLFINISHED; break; }
						case SDLK_F2: { actEnemies->add_enemy(500,200,E_NINJA); break;}
						case SDLK_F3: { actEnemies->add_enemy(600,400,E_MAGE); break;}
						case SDLK_F4: { actEnemies->add_enemy(200,300,E_ROGUE); break;}
						case SDLK_F5: { actEnemies->add_enemy(500,200,E_MAGE); break;}						
						case SDLK_F6: { this->actPlayerActionManager->enableItem(5); break; }		
						case SDLK_F7: { actPlayer->set_exp_d(1000); break; }
						case SDLK_F8: { break; }
						case SDLK_F9: {	actPlayer->set_money_d(1000); break; }
						#endif
						//movement key pressed				
						case SDLK_a:
						case SDLK_LEFT: { 								
								actPlayer->set_acc_x(-1);
								break; 
							}
						case SDLK_d:
						case SDLK_RIGHT: { 
								actPlayer->set_acc_x(1);
								break; 
							}
						case SDLK_w:
						case SDLK_UP: { 
								actPlayer->set_acc_y(-1);
								break; 
							}
						case SDLK_s:
						case SDLK_DOWN: { 
								actPlayer->set_acc_y(1);				
								break; 
							}
						case SDLK_q:
							{
								actPlayerActionManager->setNextShot();
								break;
							}
						case SDLK_p:
							{
								//actPlayerActionManager->enableNextSpell();
								//actPlayerActionManager->enableNextShot();
								break;
							}
						case SDLK_e:
							{
								actPlayerActionManager->setNextSpell();
								break;
							}
						//special meaning keys
						case SDLK_SPACE:  {	break; }
						case SDLK_RETURN: { break; }
						case SDLK_ESCAPE: { parent->goto_gs(ES_MENU); return; }
						}	
					break;
					}
				//key released
				case SDL_KEYUP:
				{	//check if the pressed key is usefull for player
					switch (handle_event.key.keysym.sym)
					{					
					
					//left,right  > back to normal
					case SDLK_a:
					case SDLK_LEFT:
					case SDLK_d:
					case SDLK_RIGHT: 
						{
							actPlayer->set_acc_x(0);							
							break;
						}
					//up,down > back to normal
					case SDLK_w:
					case SDLK_UP: 
					case SDLK_s:
					case SDLK_DOWN: 
						{ 
							actPlayer->set_acc_y(0);
							break; 
						}
			 		}
					break;
				}
				case SDL_MOUSEMOTION:		//If mouse moved
				{
				double diff_x, diff_y;
				//left of player
				if ((actPlayer->get_pos_x()+PLAYER_W*0.5) >= handle_event.button.x)	
					//over player
					if ((actPlayer->get_pos_y()+ PLAYER_H*0.2) >= handle_event.button.y) 
					{
						//III. quad; angle between 180 and 270 deg (M_PI/2 and M_PI)
						diff_x = actPlayer->get_pos_x()+PLAYER_W * 0.5 - handle_event.button.x;
						diff_y = actPlayer->get_pos_y()+PLAYER_H * 0.2 - handle_event.button.y;
						actPlayer->set_weapon_angle(M_PI-atan(diff_y/diff_x));							
					}
					//under player
					else 
					{													
						//III. quad; angle between 180 and 270 deg	, forbidden
						diff_x = actPlayer->get_pos_x()+PLAYER_W*0.5 - handle_event.button.x;
						diff_y = handle_event.button.y+PLAYER_H*0.2 - actPlayer->get_pos_y();
						//actPlayer->set_weapon_angle(atan(diff_y/diff_x)/M_PI*180);
						//actPlayer->set_weapon_angle(180);
						actPlayer->set_weapon_angle(M_PI);
					}
				//right of player
				else														
					//over player
					if ((actPlayer->get_pos_y()+PLAYER_W*0.5) >= handle_event.button.y)
					{	
						//I quad; angle between 0 and 90 deg
						diff_x = handle_event.button.x - (actPlayer->get_pos_x()+PLAYER_W*0.5);
						diff_y = actPlayer->get_pos_y() +PLAYER_H * 0.2 - handle_event.button.y;
						//actPlayer->set_weapon_angle(atan(diff_y/diff_x)/M_PI*180);
						actPlayer->set_weapon_angle(atan(diff_y/diff_x));
					}
					//under player
					else
					{		
						//IV. quad; angle between 270 and 360 deg, forbidden
						diff_x = handle_event.button.x - (actPlayer->get_pos_x()+PLAYER_W*0.5);
						diff_y = handle_event.button.y - (actPlayer->get_pos_y()+PLAYER_H * 0.2);
						//actPlayer->set_weapon_angle(atan(diff_y/diff_x)/M_PI*180);
						actPlayer->set_weapon_angle(0);							
					}			
				}
				case SDL_MOUSEBUTTONDOWN:	//If a mouse button was pressed
				{
					//tell player to shoot primary
					if( handle_event.button.button == SDL_BUTTON_LEFT ) //If the left mouse button was pressed
					{   
						//TODO: sound?  
						//TODO: manager.actShotPosition
						actPlayer->player_shoot(_t, actPlayerActionManager->getActShotPos());
						break;
					}	    
					//tell player to shoot secondary
					if( handle_event.button.button == SDL_BUTTON_RIGHT ) //If the right mouse button was pressed
					{   
						//TODO: sound?  
						//TODO: ST_HIT_COUNT + manager.actSpellPosition
						actPlayer->player_shoot(_t, actPlayerActionManager->getActSpellPos());
						break;
					}	    
					
					if(handle_event.type == SDL_MOUSEBUTTONUP ) //If a mouse button was released
					{ 
						//TODO: sound, reload?    
					}
				} //end case SDL_MOUSEBUTTONDOWN
				#ifdef _DEBUG 					
				//focus event occured
				case SDL_ACTIVEEVENT:
				{					
					//mouse focus event
					if (handle_event.active.state & SDL_APPMOUSEFOCUS)
					{					
						if (handle_event.active.gain) 
						{							
							//cout << "app mouse focus gain" << endl;							
						}
						else
						{
							//cout << "app mouse focus lost" << endl;
						}
				
					}
					//keyboard focus event
					if (handle_event.active.state & SDL_APPINPUTFOCUS)
					{
						if (handle_event.active.gain)
						{						
							//cout << "app keyb focus gain" << endl;													
						}
						else
						{
							//cout << "app keyb focus gain" << endl;													
						}
					}
					break;
				} //end case SDL_ACTIVEEVENT
				#endif
			}
			break;
	}
	case GS_NEXTLVL: //splash screen visible
		{
			if (handle_event.type == SDL_MOUSEMOTION) 
			{
				//mouse over for buttons? 
				//cout << handle_event.button.x << " " << handle_event.button.y << endl;
				break;
			}
			//handle clicks
			if ((handle_event.type == SDL_MOUSEBUTTONDOWN)&&(handle_event.button.button == SDL_BUTTON_LEFT))
			{
				int x = handle_event.button.x; //The mouse x offset
				int y = handle_event.button.y; //The mouse y offset
								
				if (actSplashScreen->process_click(x,y)) //true means village screen over
				{
					actGameState = GS_PLAY; 
					actEnemies->clean_enemies();
					actProjectils->clean_projectils();
					actMessages->clean_messages();
					actPlayer->center();
					return;
				}
			}
			if (handle_event.type = SDL_KEYDOWN)
				switch(handle_event.key.keysym.sym)
				{
					case SDLK_RETURN: 
					case SDLK_ESCAPE: 
						{
							actGameState = GS_PLAY; 
							actEnemies->clean_enemies();
							actProjectils->clean_projectils();
							actMessages->clean_messages();
							actPlayer->center();
							return;
						}
				}
			break;
		}	

	}
}
void MyGame::process_player_death()
{
	//show the message about death
	actMessages->death_message();
	parent->goto_gs(ES_SPECIAL_SCREEN);
	return;
}
